// FilterBlock.cpp
// Dopplar Radar Milestone 1
// RCOS - Griffin Milsap and Sean Austin

#include "FilterBlock.h"

using namespace std;

FilterBlock::FilterBlock()
{
  mWindowSize = 0;
  mpRawSignal = new Signal();
  mpProcessedSignal = new Signal();
}

FilterBlock::~FilterBlock()
{
  // Destruct all filters
  for( list< Filter* >::iterator itr = mFilters.begin(); itr != mFilters.end(); itr++ )
  {
    delete (*itr);
    (*itr) = NULL;
  }

  // And the raw signal
  delete mpRawSignal;
  mpRawSignal = NULL;
}

FilterBlock* FilterBlock::InsertFilter( Filter &f, int position )
{
  // Add a filter to mFilters
  if( position > mFilters.size() )
    AppendFilter( f );
  else if( position <= 0 )
    PrependFilter( f );
  else
  {
    list< Filter* >::iterator itr = mFilters.begin();
    for( int i = 0; i < position; i++ )
      itr++;
    mFilters.insert( itr, &f );
  }
  return this;
}

FilterBlock* FilterBlock::AppendFilter( Filter &f )
{
  // Put a filter at the end of the filter chain
  mFilters.push_back( &f );
  return this;
}

FilterBlock* FilterBlock::PrependFilter( Filter &f )
{
  // Add a filter at the beginning of the filter chain
  mFilters.push_front( &f );
  return this;
}

FilterBlock* FilterBlock::AddSample( Sample  &s )
{
  // Add a sample to the raw signal
  mpRawSignal->push_back( s );
  while( mpRawSignal->size() > mWindowSize )
    mpRawSignal->pop_front();
  return this;
}

bool FilterBlock::Initialize()
{
    // Allow filters to initialize themselves.
    bool ret = true;
    for( list< Filter* >::iterator itr = mFilters.begin(); itr != mFilters.end(); itr++ )
    {
      ret = (*itr)->Initialize( *mpProcessedSignal );
      if( !ret )
        break;
    }
    return ret;
}

Signal* FilterBlock::Process()
{
  // Process the current raw signal through the filter chain
  *mpProcessedSignal = *mpRawSignal;
  for( list< Filter* >::iterator itr = mFilters.begin(); itr != mFilters.end(); itr++ )
      (*itr)->Process( *mpProcessedSignal, *mpProcessedSignal );
  return mpProcessedSignal;
}

FilterBlock* FilterBlock::SetWindowSize( int n )
{
  // Set the new window size, resize raw signal if necessary
  if( n > mWindowSize )
  {
      for( int i = mWindowSize; i < n; i++ )
      {
          Sample temp;
          temp.first = 0.0f;
          temp.second = 0;
          mpRawSignal->push_back( temp );
      }
  }
  if( n < mWindowSize )
  {
    // Resize the signal
    while( mpRawSignal->size() > n )
        mpRawSignal->pop_front();
  }
  mWindowSize = n;
  return this;
}

int FilterBlock::WindowSize()
{
  // Return the window size
  return mWindowSize;
}
